 //
//  BLRoundButton.m
//  Waterflow
//
//  Created by benz on 13-11-6.
//  Copyright (c) 2013年 yangjw . All rights reserved.
//

#import "BLRoundButton.h"

@interface BLRoundButton() {
    NSOperationQueue *_queue;
}
@property (nonatomic, retain) NSMutableDictionary *imagesDicts;
@property (nonatomic, retain) NSMutableDictionary *bkImagesDicts;
@end

@implementation BLRoundButton

- (void)dealloc {
    [_imagesDicts removeAllObjects];
    [_queue cancelAllOperations];;
    _queue = nil;
}

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        _queue = [[NSOperationQueue alloc] init];
        _queue.maxConcurrentOperationCount = 1;
        _queue.name = [NSString stringWithFormat:@"%p", self];
    }
    return self;
}

- (NSInvocationOperation *)operationWithImage:(UIImage *)image state:(UIControlState)state {
    NSInvocationOperation *oper = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(setImageAndState:) object:@[image, @(state)]];
    return oper;
}

- (NSInvocationOperation *)operationWithBackgroundImage:(UIImage *)image state:(UIControlState)state {
    NSInvocationOperation *oper = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(setBackgroundImageAndState:) object:@[image, @(state)]];
    return oper;
}

- (void)setImageAndState:(NSArray *)arg {
    UIImage *image = arg.firstObject;
    UIControlState state = [arg.lastObject integerValue];
    UIImage *img = [self roundImage:image];
    dispatch_async(dispatch_get_main_queue(), ^{
        [super setImage:img forState:state];
    });
}

- (void)setBackgroundImageAndState:(NSArray *)arg {
    UIImage *image = arg.firstObject;
    UIControlState state = [arg.lastObject integerValue];
    UIImage *img = [self roundImage:image];
    dispatch_async(dispatch_get_main_queue(), ^{
        [super setImage:img forState:state];
    });
}

- (UIImage *)roundImage:(UIImage *)image {
    CGSize size = self.bounds.size;
    if (CGSizeEqualToSize(size, CGSizeZero)) {
        return image;
    }
    
    CGFloat radii = MIN(size.width, size.height)/2.0;
    CGRect frame = CGRectMake(0, 0, size.width, size.height);
    
    // Begin a new image that will be the new image with the rounded corners
    // (here with the size of an UIImageView)
    UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    //去锯齿处理
    CGContextSetAllowsAntialiasing(context, true);
    CGContextSetShouldAntialias(context, true);
    
    // Add a clip before drawing anything, in the shape of an rounded rect
    UIBezierPath *bezier = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:radii];
    [bezier addClip];
    
    if (_borderWidth>0) {
        bezier.lineWidth = _borderWidth;
        bezier.flatness = 0.1; // not work??
        [bezier stroke];
        CGContextFillRect(context, frame);
        
        UIColor *borderColor = _borderColor?:[UIColor darkGrayColor];
        CGContextSetFillColorWithColor(context, [borderColor CGColor]);
    }
    
    // Draw your image
    [image drawInRect:self.bounds];
    
    // Get the image, here setting the UIImageView image
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    
    // Lets forget about that we were drawing
    UIGraphicsEndImageContext();
    return img;
}

- (void)setImage:(UIImage *)image forState:(UIControlState)state {
    [_queue cancelAllOperations];
    if (image) {
        [self.imagesDicts setObject:image forKey:@(state)];
        NSOperation *oper = [self operationWithImage:image state:state];
        [_queue addOperation:oper];
    }
    else {
        [self.imagesDicts removeObjectForKey:@(state)];
        [super setImage:image forState:state];
    }
}

- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state {
    [_queue cancelAllOperations];
    if (image) {
        [self.bkImagesDicts setObject:image forKey:@(state)];
        NSOperation *oper = [self operationWithBackgroundImage:image state:state];
        [_queue addOperation:oper];
    }
    else {
        [self.bkImagesDicts removeObjectForKey:@(state)];
        [super setBackgroundImage:image forState:state];
    }
}

- (void)setBounds:(CGRect)bounds {
    BOOL isChanged = !CGSizeEqualToSize(self.bounds.size, bounds.size);
    [super setBounds:bounds];
    
    if (isChanged) {
        [self updateImages];
    }
}

- (void)setFrame:(CGRect)frame {
    BOOL isChanged = !CGSizeEqualToSize(self.frame.size, frame.size);
    [super setFrame:frame];
    
    if (isChanged) {
        [self updateImages];
    }
}

- (void)updateImages {
    for (NSNumber *key in self.imagesDicts.allKeys) {
        UIImage *image = self.imagesDicts[key];
        if (image) {
            UIControlState state = key.integerValue;
            [self setImage:image forState:state];
        }
    }
    for (NSNumber *key in self.bkImagesDicts.allKeys) {
        UIImage *image = self.bkImagesDicts[key];
        if (image) {
            UIControlState state = key.integerValue;
            [self setBackgroundImage:image forState:state];
        }
    }
}

#pragma mark - Getters

- (NSMutableDictionary *)imagesDicts {
    if (!_imagesDicts) {
        _imagesDicts = [NSMutableDictionary dictionaryWithCapacity:0];
    }
    return _imagesDicts;
}

- (NSMutableDictionary *)bkImagesDicts {
    if (!_bkImagesDicts) {
        _bkImagesDicts = [NSMutableDictionary dictionaryWithCapacity:0];
    }
    return _bkImagesDicts;
}

@end


static inline double Radians(CGFloat degrees) {
    double f = (degrees/ 180.0) * M_PI; // or M_PI in math.h.
    return f;
};

@implementation BLRoundAttachButton

- (void)attachView:(UIView *)view degress:(CGFloat)degress {
    double radians = Radians(degress);
    CGFloat radius = CGRectGetHeight(self.bounds)/2.0;
    CGFloat y = radius*sinl(radians);
    CGFloat x = radius*cosl(radians);
    CGPoint center = view.center;
    center.x = ceilf(radius+x);
    center.y = ceilf(radius-y);
    view.center = center;
    [self addSubview:view];
}

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        _attachViewDegress = -45;
    }
    return self;
}

- (void)setAttachView:(UIView *)attachView {
    if (attachView!=_attachView) {
        [_attachView removeFromSuperview];
        if (attachView) {
            [self attachView:attachView degress:_attachViewDegress];
            _attachView = attachView;
        }
    }
}

- (void)setBounds:(CGRect)bounds {
    BOOL change = !CGRectEqualToRect(bounds, self.bounds);
    [super setBounds:bounds];
    if (change) {
        [self attachView:_attachView degress:_attachViewDegress];
    }
}
@end

